package com.binguo.wxapi.service;

import com.alibaba.fastjson.JSONObject;
import com.binguo.common.enums.*;
import com.binguo.common.exception.ServiceException;
import com.binguo.common.paymodel.ThreadManager;
import com.binguo.common.paymodel.WXResponse;
import com.binguo.common.paymodel.YilingPayResult;
import com.binguo.common.util.LoggerUtil;
import com.binguo.common.util.PriceUtil;
import com.binguo.helper.FaceHelperV3;
import com.binguo.model.mapper.BinguoOrderMapper;
import com.binguo.model.mapper.CustomerExtendMapper;
import com.binguo.model.mapper.CustomerMapper;
import com.binguo.model.mapper.PayCardMapper;
import com.binguo.model.model.*;
import com.binguo.model.repository.*;
import com.binguo.model.wxapi.vo.BannerVO;
import com.binguo.model.wxapi.vo.CaoGenYaoPayCardVO;
import com.binguo.model.wxapi.vo.CardsVO;
import com.binguo.service.*;
import com.binguo.socket.service.MenJinSocketService;
import com.binguo.thirdPay.caoGenYaoPay.CaoGenYaoPay;
import com.binguo.thirdPay.jinQiao.JinQiaoPayCardItem;
import com.binguo.thirdPay.jinQiao.JinQiaoPayController;
import com.binguo.thirdPay.zy.ZytkService;
import com.binguo.wxapi.form.CancelCardForm;
import com.binguo.wxapi.form.RechargeCardForm;
import com.binguo.wxapi.form.UpdateCardForm;
import com.binguo.wxapi.transfer.WXCardsTransfer;
import com.binguo.wxapi.util.BarcodeUtil;
import com.binguo.wxapi.wxpay.WxPayServiceNew;
import com.tencentcloudapi.iai.v20180301.models.GetPersonBaseInfoResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Condition;

import javax.annotation.Resource;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.binguo.common.exception.ErrorCode.*;


/**
 * Created by jay on 18/5/20.
 */
@Service
public class WXCardService {

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");

    @Autowired
    FaceRepository faceRepository;

    @Resource
    CustomerMapper customerMapper;

    @Resource
    PayCardMapper payCardMapper;

    @Autowired
    PayCardRepository payCardRepository;

    @Autowired
    ShopService shopService;

    @Autowired
    WXCardsTransfer wXCardsTransfer;

    @Autowired
    BinguoOrderRepository binguoOrderRepository;

    @Resource
    BinguoOrderMapper binguoOrderMapper;

    @Autowired
    WXPayService wxPayService;

    @Autowired
    DeleteFaceRepository deleteFaceRepository;

    @Autowired
    BannerRepository bannerRepository;

    @Autowired
    ZytkService zytkService;

    @Autowired
    CustomerService customerService;

    @Autowired
    WxPayServiceNew wxPayServiceNew;
    @Autowired
    OrderService orderService;

    @Autowired
    DeviceMsgTemporaryRepository deviceMsgTemporaryRepository;

    @Autowired
    DeviceMsgService deviceMsgService;

    @Autowired
    CaoGenYaoPay caoGenYaoPay;

    @Autowired
    ShopCaogenyaoConfigRepository shopCaogenyaoConfigRepository;

    @Autowired
    CaogenyaoPaycardRepository caogenyaoPaycardRepository;

    @Autowired
    MenJinSocketService menJinSocketService;

    @Autowired
    CashierDeskExtendRepository cashierDeskExtendRepository;

    @Autowired
    AliServerPayService aliServerPayService;

    @Resource
    RechargeService rechargeService;

    private static Logger logger = LoggerFactory.getLogger(WXCardService.class);

    /**
     * 免密支付解约成功，设置contractId为空
     */
    public void deleteContractNotity(String contractCode){
        Condition condition = new Condition(PayCard.class);
        condition.or()
                .andEqualTo("contractCode", contractCode);
        Optional<PayCard> payCardOptional = payCardRepository.findByCondition(condition).stream().findFirst();
        if(payCardOptional.isPresent()){
            PayCard payCard = payCardOptional.get();
            payCard.setContractId(null);
            payCardRepository.update(payCard);
        } else throw new ServiceException(WX_PAYCARD_NOT_EXIST);
    }


    /**
     * 免密支付签约成功,设置contractId
     */
    public void contractNotity(String contractCode, String contractId){
        Condition condition = new Condition(PayCard.class);
        condition.or()
                .andEqualTo("contractCode", contractCode);
        Optional<PayCard> payCardOptional = payCardRepository.findByCondition(condition).stream().findFirst();
       if(payCardOptional.isPresent()){
           PayCard payCard = payCardOptional.get();
           payCard.setContractId(contractId);
           payCardRepository.update(payCard);
       } else throw new ServiceException(WX_PAYCARD_NOT_EXIST);
    }


    /**
     * 免密支付解约
     */
    public Boolean deleteContract(Integer cardId) throws Exception {
        PayCard payCard = payCardRepository.findById(cardId);
        if(payCard == null) throw new ServiceException(WX_PAYCARD_NOT_EXIST);
        String contractId = payCard.getContractId();
        if(contractId == null) throw new ServiceException(PAYCARD_NOT_CONTRACT);
       return wxPayService.deletecontract(contractId);

    }


    /**
     * 修改免密支付ContractCode
     */
    public void updateContractCode(Integer cardId, String contractCode){
        PayCard payCard = payCardRepository.findById(cardId);
        if(payCard == null) throw new ServiceException(WX_PAYCARD_NOT_EXIST);
        payCard.setContractCode(contractCode);
        payCardRepository.update(payCard);
    }

    public List<BannerVO> bannerList(){
        Condition condition = new Condition(Banner.class);
        condition.or().andEqualTo("status", 1);
       return wXCardsTransfer.toBannerVOList(bannerRepository.findByCondition(condition));
    }

    public List<CardsVO> list(Integer customerId){
       return wXCardsTransfer.toShopsVOList(findByCustomerId(customerId));
    }


    public String getPayCode(Integer cardId){
        PayCard payCard = payCardRepository.findById(cardId);
        if(payCard == null) throw new ServiceException(WX_PAYCARD_NOT_EXIST);
        String payCode = BarcodeUtil.createPayCode("" + payCard.getId());
        payCard.setPayCode(payCode);
        payCard.setPayCodeTime(new Date());
        payCardRepository.update(payCard);

        String imgBase64 = BarcodeUtil.generateFile(payCode);
        return imgBase64;
    }



    /**
     * 退卡
     */
    @Transactional
    public void cancelcard(CancelCardForm form){

        PayCard payCard = findPayCardByCardNo(form.getCustomerId(), form.getCardNo());

        Shop shop = shopService.findShopById(payCard.getShopid());

        if (StringUtils.hasText(shop.getInvitecode())) {
            if (payCard.getWxAccountbalance() > 0) {
                throw new ServiceException("卡余额不为0,无法退卡");
            }
        }

        Long accountbalance = payCard.getWxAccountbalance();

        //如果退卡的为主卡,设置用户其他任意一张为主卡
        if(payCard.getIsmaster()){
            Optional<PayCard> cardOptional = findBinguoCardByCustomerId(form.getCustomerId()).stream().findFirst();
            if(cardOptional.isPresent()){
                PayCard payCard1 =cardOptional.get();
                payCard1.setIsmaster(true);
                payCardRepository.update(payCard1);
            }
        }

        if(accountbalance > 0){
            //更新accountbalance
//            payCard.setAccountbalance(0L);
            payCard.setWxAccountbalance(0L);
            payCard.setDeleted(true);
            payCardRepository.update(payCard);

            //卡余额涉及多笔充值订单
            List<BinguoOrder> orders = findOrderByCard(payCard);
            for(BinguoOrder order: orders){
               Long balance = accountbalance - order.getRealfee();
               if(balance == 0){ //订单全部退款
                   order.setRefundfee(order.getRealfee());
                   order.setRefundstatus(RefundStatus.REFUND_DEALING.getCode().byteValue());
                   order.setUpdated(new Date());
                   binguoOrderRepository.update(order);
                   wxPayService.doRefund(order.getOrderno(), order.getRealfee().toString(), order.getRealfee().toString());
                   return;
               } else if(balance < 0){ //订单部分退款
                   order.setRefundfee(accountbalance);
                   order.setRefundstatus(RefundStatus.REFUND_DEALING.getCode().byteValue());
                   order.setUpdated(new Date());
                   binguoOrderRepository.update(order);
                   wxPayService.doRefund(order.getOrderno(), order.getRealfee().toString(), accountbalance.toString());
                   return;
               } else { //订单全部退款
                   order.setRefundfee(order.getRealfee());
                   order.setRefundstatus(RefundStatus.REFUND_DEALING.getCode().byteValue());
                   order.setUpdated(new Date());
                   binguoOrderRepository.update(order);
                   wxPayService.doRefund(order.getOrderno(), order.getRealfee().toString(), order.getRealfee().toString());
                   //更新accountbalance
                   accountbalance = accountbalance - order.getRealfee();
               }

            }
        } else if(accountbalance  == 0 ){
//            payCard.setAccountbalance(0L);
            payCard.setWxAccountbalance(0L);
            payCard.setDeleted(true);
            payCardRepository.update(payCard);
        }
        Condition condition = new Condition(Face.class);
        condition.or().andEqualTo("persionid",payCard.getShopid() + "_" + form.getCustomerId());

        List<Face> faceList = faceRepository.findByCondition(condition);

        if (FaceHelperV3.deletePerson(payCard.getShopid() + "_" + form.getCustomerId())){

//            faceRepository.deleteByCondition(condition);
        }else {
            DeleteFace deleteFace = new DeleteFace();
            deleteFace.setDeleteCustomerid(payCard.getShopid() + "_" + form.getCustomerId());
            deleteFaceRepository.save(deleteFace);
        }

        faceRepository.deleteByCondition(condition);



        if (faceList != null && faceList.size() > 0) {
            for (Face face : faceList) {
                deviceMsgService.addDeviceMsg(payCard.getShopid(), payCard.getCustomerid(),
                        payCard.getName(), face.getFaceurl(),
                        "0", face.getFaceid());
            }
        }

    }


    /**
     * 充值卡
     */
    @Transactional
    public WXResponse recharge(RechargeCardForm form, String ip, Shop shop){
        if (shop.getWxPayFunction() != null && shop.getWxPayFunction() == 0) {
            throw new ServiceException("商户不允许微信充值");
        }

        String uuid = UUID.randomUUID().toString().replace("-", "");

        String orderNo = "Mi" + uuid.substring(0, uuid.length() - 4);

        BinguoOrder order = BinguoOrder.builder()
                .orderno(orderNo)
                .cardid(form.getCardId())
                .shopid(form.getShopId())
                .openid(form.getOpenId())
                .customerid(form.getCustomerId())
                .customername(form.getCustomerName())
                .customerphone(form.getCustomerPhone())
                .source(PayType.OTHERPAY.getCode().byteValue())
                .totalfee(form.getRechargeFee())
                .realfee(form.getRechargeFee())
                .totalquantity(1)
                .ordertype(OrderType.CARD.getCode())
                .paystatus(PayStatus.PAYING.getCode().byteValue())
                .refundstatus(RefundStatus.UN_REFUND.getCode().byteValue())
                .build();
        binguoOrderRepository.save(order);

        String attach = "虚拟卡号:" + form.getCardNo();
        return wxPayService.wxpay(form.getOpenId(), orderNo, form.getRechargeFee().toString(), attach, ip);

    }

    /**
     * 充值卡
     */
    @Transactional
    public WXResponse rechargeChoise(RechargeCardForm form, String ip) {
        Shop shop = shopService.findShopById(form.getShopId());
        if (shop == null) {
            throw new ServiceException("param error");
        }

//        if (StringUtils.hasText(shop.getInvitecode())) {
            if (shop.getSubMchId() != null && shop.getSubMchId().length() > 10) {
                if (shop.getId().intValue() == 199) {//百岁小碗定制，充值到渠道号下微信账号
                    shop.setSubAppid("000000000193035");
                    shop.setAliMchId("2ba5c350b6afc8850e34f046aed55164");
                }
                return rechargeByYiLingServerPay(form, ip, shop);
            }
            return rechargeByServerPay(form, ip, shop);
//        }else {
//            return recharge(form, ip, shop);
//        }
    }

    /**
     * 充值卡
     */
    @Transactional
    public WXResponse rechargeByServerPay(RechargeCardForm form, String ip, Shop shop){
        if (shop.getWxPayFunction() != null && shop.getWxPayFunction() == 0) {
            throw new ServiceException("商户不允许微信充值");
        }

        String uuid = UUID.randomUUID().toString().replace("-", "");

        String orderNo = "Mi" + uuid.substring(0, uuid.length() - 4);
        BinguoOrder order = BinguoOrder.builder()
                .orderno(orderNo)
                .cardid(form.getCardId())
                .shopid(form.getShopId())
                .openid(form.getOpenId())
                .customerid(form.getCustomerId())
                .customername(form.getCustomerName())
                .customerphone(form.getCustomerPhone())
                .source(PayType.OTHERPAY.getCode().byteValue())
                .totalfee(form.getRechargeFee())
                .realfee(form.getRechargeFee())
                .totalquantity(1)
                .ordertype(OrderType.CARD.getCode())
                .paystatus(PayStatus.PAYING.getCode().byteValue())
                .refundstatus(RefundStatus.UN_REFUND.getCode().byteValue())
                .build();
        binguoOrderRepository.save(order);

        String attach = "虚拟卡号:" + form.getCardNo();
        return wxPayServiceNew.wxpay(form.getOpenId(), orderNo, form.getRechargeFee().toString(), attach, ip,
                        null, null, shop.getSubMchId(), null

                );

    }


    /**
     * 移领间连小程序充值
     */
    public WXResponse rechargeByYiLingServerPay(RechargeCardForm form, String ip, Shop shop){
        logger.info("rechargeByYiLingServerPay: customerId:{}, shopId:{}", form.getCustomerId(), shop.getId());
        if (shop.getWxPayFunction() != null && shop.getWxPayFunction() == 0) {
            throw new ServiceException("商户不允许微信充值");
        }

        String uuid = UUID.randomUUID().toString().replace("-", "");

        String orderNo = "Mi" + uuid.substring(0, uuid.length() - 4);

        CustomerExtend customerExtend = customerService.getCustomerExtend(form.getCustomerId(),form.getShopId());

        WXResponse wxResponse = aliServerPayService.miniPay(orderNo, form.getRechargeFee().toString(), shop.getSubAppid(), shop.getAliMchId(), form.getOpenId());
        BinguoOrder order = BinguoOrder.builder()
                .orderno(orderNo)
                .cardid(form.getCardId())
                .shopid(form.getShopId())
                .openid(form.getOpenId())
                .customerid(form.getCustomerId())
                .customergroupid(customerExtend.getGroupId())
                .customername(form.getCustomerName())
                .customerphone(form.getCustomerPhone())
                .source(PayType.OTHERPAY.getCode().byteValue())
                .totalfee(form.getRechargeFee())
                .realfee(form.getRechargeFee())
                .totalquantity(1)
                .ordertype(OrderType.CARD.getCode())
                .paystatus(PayStatus.PAYING.getCode().byteValue())
                .refundstatus(RefundStatus.UN_REFUND.getCode().byteValue())
                .yilingTradeNum(wxResponse.getCodeUrl())
                .build();
        binguoOrderRepository.save(order);


        ThreadManager.executorService.submit(() -> {
            boolean doWhile = false;
            int count = 0;
            while(!doWhile) {
                try {
                    Thread.sleep(5 * 1000); //设置暂停的时间 5 秒
                    count ++ ;
                    logger.info(sdf.format(new Date()) + "--微信支付订单查询支付状态请求第" + count + "次");


                    String orderQueryResult = aliServerPayService.doQuery(orderNo, wxResponse.getCodeUrl(), shop.getSubAppid(), shop.getAliMchId());

                    logger.info("order_result_code : {}" , orderQueryResult);

                    if ("SUCCESS".equals(orderQueryResult)) {
                        Optional<BinguoOrder> binguoOrder = orderService.findByOrderNo(orderNo);
                        if (binguoOrder.isPresent()) {
                            if (binguoOrder.get().getPaystatus().equals(PayStatus.PAYING.getCode().byteValue())) {
                                BinguoOrder temp = new BinguoOrder();
                                temp.setPaystatus(PayStatus.SUCCESS.getCode().byteValue());
                                temp.setId(binguoOrder.get().getId());

                                Condition condition = new Condition(PayCard.class);
                                condition.or().andEqualTo("customerid", form.getCustomerId())
                                        .andEqualTo("shopid", shop.getId())
                                        .andEqualTo("deleted", false);

                                List<PayCard> payCardList = payCardRepository.findByCondition(condition);

                                if (payCardList != null && payCardList.size() > 0) {
                                    PayCard payCard = payCardList.get(0);
                                    PayCard tempPayCard = new PayCard();
                                    JSONObject result = rechargeService.getWxRechargeMoney(shop.getId(),form.getCustomerId(),form.getRechargeFee());
                                    Long rechargeFee = result.getLong("rechargeMoney") - form.getRechargeFee();
                                    tempPayCard.setId(payCard.getId());
                                    tempPayCard.setWxAccountbalance(payCard.getWxAccountbalance() + form.getRechargeFee());
                                    tempPayCard.setAccountbalance(payCard.getAccountbalance()+rechargeFee);
                                    temp.setNote(result.getString("note"));
                                    temp.setWxMoney(form.getRechargeFee());
                                    temp.setMoney(rechargeFee);
                                    payCardMapper.updateByPrimaryKeySelective(tempPayCard);
                                }
                                binguoOrderMapper.updateByPrimaryKeySelective(temp);
                            }
                        }
                    }else {
                        if(!"PAYING".equals(orderQueryResult)){
                            Optional<BinguoOrder> binguoOrder = orderService.findByOrderNo(orderNo);
                            if (binguoOrder.isPresent()) {
                                if (binguoOrder.get().getPaystatus().equals(PayStatus.PAYING.getCode().byteValue())) {
                                    BinguoOrder temp = new BinguoOrder();
                                    temp.setPaystatus(PayStatus.CANCELED.getCode().byteValue());

                                    temp.setId(binguoOrder.get().getId());

                                    binguoOrderMapper.updateByPrimaryKeySelective(temp);
                                }
                            }
                            break;
                        }
                    }

                    if (count == 6) {
                        doWhile = true;
                        Optional<BinguoOrder> binguoOrder = orderService.findByOrderNo(orderNo);
                        if (binguoOrder.isPresent()) {
                            if (binguoOrder.get().getPaystatus().equals(PayStatus.PAYING.getCode().byteValue())) {
                                BinguoOrder temp = new BinguoOrder();
                                temp.setPaystatus(PayStatus.CANCELED.getCode().byteValue());

                                temp.setId(binguoOrder.get().getId());

                                binguoOrderMapper.updateByPrimaryKeySelective(temp);
                            }
                        }

                        //撤销订单
                        break;
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        return wxResponse;

    }




    /**
     * @param form
     * 修改支付卡
     */
    @Transactional
    public void updateCard(UpdateCardForm form){
        //切换主卡时需要设置其他卡为副卡
        if(form.getIsMaster()){
            List<PayCard> cards = findByCustomerId(form.getCustomerId());
            cards.forEach(card -> {
                card.setIsmaster(false);
                payCardRepository.update(card);
            });
        }

        PayCard payCard = findById(form.getCardId(), form.getCustomerId());
        payCard.setName(form.getName());
        payCard.setIsmaster(form.getIsMaster());
        payCard.setIsnopasswordpay(form.getIsNoPasswordPay());
        payCardRepository.update(payCard);

        List<PayCard> cardList = findMasterCardByCustomerId(form.getCustomerId());
        if(cardList.isEmpty()) {
            throw new ServiceException(PAYCARD_NOT_HAVE_MASTER);
        }

    }


    public void createYKTCard(Integer shopId, Integer customerId, String cardNo, Integer cardType){

        Optional<PayCard> payCardOptional = findEmptyPayCardByCardNo(customerId, cardNo);

        if(payCardOptional.isPresent()){
            PayCard payCard = payCardOptional.get();
            payCard.setDeleted(false);
            payCardRepository.update(payCard);
        } else {

            Shop shop = shopService.findShopById(shopId);

            if (shop == null) {
                return;
            }

            Customer customer = customerService.findByCustomerId(customerId);

            if (customer == null) {
                throw new ServiceException("用户不存在");
            }

            if (StringUtils.isEmpty(customer.getPhone())) {
                throw new ServiceException("请先申请虚拟卡");
            }

            //金桥逻辑
            if (shop.getPayType() == 8) {
                JinQiaoPayCardItem jinQiaoPayCardItem = JinQiaoPayController.GetCardInfoByMemInterface(cardNo);

                if (jinQiaoPayCardItem == null) {
                    throw new ServiceException("卡号错误");
                }

                if (customer.getPhone() != null && customer.getPhone().equals(jinQiaoPayCardItem.getMobilePhone())) {
                    System.out.println("用户匹配:" + jinQiaoPayCardItem.getMobilePhone());
                } else {
                    throw new ServiceException("用户不匹配");
                }

                Long balance = jinQiaoPayCardItem.getCurrentMoney();

                String name = jinQiaoPayCardItem.getTrueName() + "的一卡通";
                PayCard payCard = PayCard.builder()
                        .shopid(shopId)
                        .customerid(customerId)
                        .accountbalance(balance)
                        .cardno(cardNo)
                        .cardtype(cardType.byteValue())
                        .name(name).build();
                payCardRepository.save(payCard);
                return;
            }
            //正元逻辑
            if (shop.getPayType() == 7){
                Map<String, Object> result;
                try {
                    result = zytkService.GetAccInfo(cardNo, shopId);
                } catch (Exception e) {
                    throw new ServiceException(WX_PAYCARD_NOT_EXIST);
                }

                String phone = (String) result.get("mobilePhone");

                if (customer.getPhone() != null && customer.getPhone().equals(phone)) {
                    System.out.println("用户匹配:" + phone);
                } else {
                    throw new ServiceException("用户不匹配");
                }

                Long balance = 0l;
                try {
                    String tempBalance = zytkService.GetAccDBMoney(cardNo, shopId, ZytkService.cardType);
                    balance = Long.valueOf(tempBalance);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new ServiceException("用户不匹配");
                }

                String name = result.get("customerName") + "的一卡通";
                PayCard payCard = PayCard.builder()
                        .shopid(shopId)
                        .customerid(customerId)
                        .accountbalance(balance)
                        .cardno(cardNo)
                        .cardtype(cardType.byteValue())
                        .name(name).build();
                payCardRepository.save(payCard);

                return;
            }

            if (shop.getPayType() == 16){
                ShopCaogenyaoConfig config = shopService.getCaoGenYaoConfig(shopId);
                List<CaoGenYaoPayCardVO> cardList = caoGenYaoPay.findCardNoByValue(customer.getPhone(),config.getCgyCompanyId(),config.getCgyCardtypeId(),config.getCgyShopId(),2);
                Boolean cardResult = false;
                for (CaoGenYaoPayCardVO cardVO: cardList){
                    if (cardVO.getCardNo().equals(cardNo)){
                        Condition cardCondition = new Condition(CaogenyaoPaycard.class);
                        cardCondition.or().andEqualTo("customerid",customerId);
                        List<CaogenyaoPaycard> caogenyaoPaycardList = caogenyaoPaycardRepository.findByCondition(cardCondition);
                        CaogenyaoPaycard caogenyaoPaycard;
                        if (null == caogenyaoPaycardList || caogenyaoPaycardList.size() == 0){
                            caogenyaoPaycard = new CaogenyaoPaycard();
                            caogenyaoPaycard.setCustomerid(customerId);
                            caogenyaoPaycard.setCardid(Long.parseLong(cardVO.getCardId()));
                            caogenyaoPaycardRepository.save(caogenyaoPaycard);
                        }else {
                            caogenyaoPaycard = caogenyaoPaycardList.get(0);
                            caogenyaoPaycard.setCardid(Long.parseLong(cardVO.getCardId()));
                            caogenyaoPaycardRepository.update(caogenyaoPaycard);
                        }
                        cardResult = true;
                        break;
                    }
                }
                if (cardResult){
                    PayCard payCard = customerService.getCustomerPayCard(customerId,shopId);
                    payCard.setCardno(cardNo);
                    payCard.setDeleted(false);
                    payCardRepository.update(payCard);
                    return;
                }else {
                    throw new ServiceException("输入卡号有误");
                }
            }

        }

        throw new ServiceException("暂不支持此商户的一卡通");
    }

    public void deleteYKTCard(Integer customerId, String cardNo){
        PayCard payCard = findPayCardByCardNo(customerId, cardNo);
        payCard.setDeleted(true);
        payCardRepository.update(payCard);
    }


    /**
     *
     * @param shopId
     * @param customerId
     * @param faceUrl
     * @param cardType
     * 创建支付卡
     */
    @Transactional
    public String createCard(Integer shopId, Integer customerId, String faceUrl, Integer cardType){

        Shop shop = shopService.findShopById(shopId);
        Customer customer = customerService.findByCustomerId(customerId);
        String cardNO = "";



        int score = FaceHelperV3.detectFace(shopId, faceUrl);
        if (score < 70) {
            throw new ServiceException("人脸图片质量不合格");
        }

        Condition condition = new Condition(PayCard.class);
        condition.or()
                .andEqualTo("customerid", customerId)
                .andEqualTo("shopid", shopId)
                .andEqualTo("cardtype", CardType.BINGUO_CARD.getCode().byteValue());

        Optional<PayCard> payCardOptional = payCardRepository.findByCondition(condition).stream().findFirst();

        String faceId = null;
        if(payCardOptional.isPresent()){

            PayCard payCard = payCardOptional.get();
            if (StringUtils.hasText(cardNO)) {
                payCard.setCardno(cardNO);
            }
            payCard.setDeleted(false);
            payCardRepository.update(payCard);

            String personId = shopId + "_" + customerId;
            FaceHelperV3.deletePerson(personId);
            faceId = FaceHelperV3.createPerson(shopId.toString(), personId, faceUrl);

            if (faceId == null) {
                faceId = FaceHelperV3.createPerson(shopId.toString(), personId, faceUrl);
                if (faceId == null) {
                    throw new ServiceException(UPLOAD_ERROR);
                }
            }
            Face face = new Face();
            face.setFaceid(faceId);
            face.setFaceurl(faceUrl);
            face.setPersionid(personId);
            face.setCustomerId(customerId);
            face.setIsDeleted(0);
            faceRepository.save(face);

            addCustomerExtend(shopId, customerId, faceId, faceUrl);

            return payCard.getId().toString();
        } else {

            String personId = shopId + "_" + customerId;

            //检查是否已经创建过
//            if(faceRepository.findBy("persionid", personId) != null) throw new ServiceException(WX_PAYCARD_IS_EXIST);

            Condition faceCondition = new Condition(Face.class);
            faceCondition.or().andEqualTo("customerId", customerId);
            List<Face> faceList = faceRepository.findByCondition(faceCondition);

            List<String> personIdList = null;
            if (faceList != null && faceList.size() > 0) {
                personIdList =
                        faceList.stream().map(f -> f.getPersionid()).collect(Collectors.toList());
            }

            //todo: 在人脸列表添加的图片，也需要添加到这个商户groupId下

            if (faceList != null && faceList.size() > 0
                    && personIdList.contains(personId)
                    ) {
                //添加人脸
                faceId = FaceHelperV3.addFace(shopId + "_" + customerId, faceUrl);
                if (faceId == null) {
                    throw new ServiceException(UPLOAD_ERROR);
                }
                Face face = new Face();
                face.setFaceid(faceId);
                face.setFaceurl(faceUrl);
                face.setPersionid(personId);
                face.setCustomerId(customerId);
                face.setIsDeleted(0);
                faceRepository.save(face);
            }else {
                //创建人脸信息
                try {
                    faceId = FaceHelperV3.createPerson(shopId.toString(),
                            shopId + "_" + customerId, faceUrl);
                    if (faceId == null) {
                        throw new ServiceException(UPLOAD_ERROR);
                    }
                    Face face = new Face();
                    face.setFaceid(faceId);
                    face.setIsDeleted(0);
                    face.setFaceurl(faceUrl);
                    face.setPersionid(personId);
                    face.setCustomerId(customerId);
                    faceRepository.save(face);
                }catch (Exception e){
                    e.printStackTrace();

                    GetPersonBaseInfoResponse getPersonBaseInfoResponse =
                            FaceHelperV3.getPersonBaseInfo(shopId + "_" + customerId);
                    if (getPersonBaseInfoResponse != null && getPersonBaseInfoResponse.getFaceIds() != null) {
                        Face face = new Face();
                        faceId = getPersonBaseInfoResponse.getFaceIds()[0];
                        face.setFaceid(faceId);
                        face.setFaceurl(faceUrl);
                        face.setPersionid(personId);
                        face.setIsDeleted(0);
                        face.setCustomerId(customerId);
                        faceRepository.save(face);
                    } else {
                        throw new ServiceException(UPLOAD_ERROR);
                    }
                }

            }


            //查询用户虚拟卡记录
            List<PayCard> cardList = findBinguoCardByCustomerId(customerId);

            //创建支付卡
            String name = shopService.findShopNameById(shopId) + "卡";
            PayCard payCard = new PayCard();
            payCard.setShopid(shopId);
            payCard.setCustomerid(customerId);
            payCard.setCardtype(CardType.BINGUO_CARD.getCode().byteValue());
            payCard.setName(name);
            if(cardList.isEmpty()) {
                payCard.setIsmaster(true);
            } else {
                payCard.setIsmaster(false);
            }
            payCardRepository.save(payCard);
            String cardNo = payCard.getId().toString();
            payCard.setCardno(cardNo);
            payCardRepository.update(payCard);

            addCustomerExtend(shopId, customerId, faceId, faceUrl);

            return cardNO;
        }

    }

    /**
     *
     * @param shopId
     * @param customerId
     * 创建支付卡
     */
    @Transactional
    public String createCardNew2(Integer shopId, Integer customerId, String customerName, Integer groupId){

        Shop shop = shopService.findShopById(shopId);
        Customer customer = customerService.findByCustomerId(customerId);

        if (StringUtils.hasText(customerName)) {
            Customer temp = new Customer();
            temp.setName(customerName);
            temp.setUpdated(new Date());
            temp.setId(customerId);
            customerMapper.updateByPrimaryKeySelective(temp);
        }
        String cardNO = "";

        Condition condition = new Condition(PayCard.class);
        condition.or()
                .andEqualTo("customerid", customerId)
                .andEqualTo("shopid", shopId)
                .andEqualTo("cardtype", CardType.BINGUO_CARD.getCode().byteValue());

        Optional<PayCard> payCardOptional = payCardRepository.findByCondition(condition).stream().findFirst();

        if(payCardOptional.isPresent()){

            PayCard payCard = payCardOptional.get();
            if (StringUtils.hasText(cardNO)) {
                payCard.setCardno(cardNO);
            }
            payCard.setDeleted(false);
            payCardRepository.update(payCard);

            addCustomerExtendNew(customer, shop, groupId);

            addFace(customerId, shopId);

            return payCard.getId().toString();
        } else {

            //查询用户虚拟卡记录
            List<PayCard> cardList = findBinguoCardByCustomerId(customerId);

            //创建支付卡
            String name = shopService.findShopNameById(shopId) + "卡";
            PayCard payCard = new PayCard();
            payCard.setShopid(shopId);
            payCard.setCustomerid(customerId);
            payCard.setCardtype(CardType.BINGUO_CARD.getCode().byteValue());
            payCard.setName(name);
            if(cardList.isEmpty()) {
                payCard.setIsmaster(true);
            } else {
                payCard.setIsmaster(false);
            }
            payCardRepository.save(payCard);
            String cardNo = payCard.getId().toString();
            payCard.setCardno(cardNo);
            payCardRepository.update(payCard);


            addCustomerExtendNew(customer, shop, groupId);
            addFace(customerId, shopId);

            return cardNO;
        }

    }



    /**
     * @param shopId
     * @param customerId
     * @param faceUrl
     * @param cardType
     * 创建支付卡(新方法)
     */
    @Transactional
    public String createCardNew(Integer shopId, Integer customerId, String faceUrl, Integer cardType) {

        int score = FaceHelperV3.detectFace(shopId, faceUrl);
        if (score < 70) {
            throw new ServiceException("人脸图片质量不合格");
        }

        Condition condition = new Condition(PayCard.class);
        condition.or()
                .andEqualTo("customerid", customerId)
                .andEqualTo("shopid", shopId)
                .andEqualTo("cardtype", CardType.BINGUO_CARD.getCode().byteValue());

        Optional<PayCard> payCardOptional = payCardRepository.findByCondition(condition).stream().findFirst();

        if (payCardOptional.isPresent()) {

            FaceHelperV3.deletePerson(shopId + "_" + customerId);
            String faceID = FaceHelperV3.createPerson(shopId.toString(), shopId + "_" + customerId, faceUrl);
            if (faceID == null) {
                throw new ServiceException("创建人脸失败");
            }
            Face face = new Face();
            face.setFaceid(faceID);
            face.setFaceurl(faceUrl);
            face.setPersionid(shopId + "_" + customerId);
            face.setCustomerId(customerId);
            faceRepository.save(face);

            PayCard payCard = payCardOptional.get();
            payCard.setDeleted(false);
            payCardRepository.update(payCard);


            return payCard.getId().toString();
        } else {

            String personId = shopId + "_" + customerId;

            Condition faceCondition = new Condition(Face.class);
            faceCondition.or().andEqualTo("customerId", customerId);
            List<Face> faceList = faceRepository.findByCondition(faceCondition);

            List<String> personIdList = null;
            if (faceList != null && faceList.size() > 0) {
                personIdList =
                        faceList.stream().map(f -> f.getPersionid()).collect(Collectors.toList());
            }

            for (String addPersonID : personIdList) {
                String faceID = FaceHelperV3.addFace(addPersonID,faceUrl);
                if (faceID != null){
                    Face face = new Face();
                    face.setFaceid(faceID);
                    face.setFaceurl(faceUrl);
                    face.setPersionid(addPersonID);
                    face.setCustomerId(customerId);
                    faceRepository.save(face);
                }
            }


            //创建人脸信息
            try {
                String faceId = FaceHelperV3.createPerson(shopId.toString(),
                        shopId + "_" + customerId, faceUrl);
                if (faceId == null) {
                    throw new ServiceException(UPLOAD_ERROR);
                }
                Face face = new Face();
                face.setFaceid(faceId);
                face.setFaceurl(faceUrl);
                face.setPersionid(personId);
                face.setCustomerId(customerId);
                faceRepository.save(face);
            } catch (Exception e) {
                e.printStackTrace();
                throw new ServiceException(UPLOAD_ERROR);
            }


            //查询用户虚拟卡记录
            List<PayCard> cardList = findBinguoCardByCustomerId(customerId);

            //创建支付卡
            String name = shopService.findShopNameById(shopId) + "卡";
            PayCard payCard = new PayCard();
            payCard.setShopid(shopId);
            payCard.setCustomerid(customerId);
            payCard.setCardtype(CardType.BINGUO_CARD.getCode().byteValue());
            payCard.setName(name);
            if (cardList.isEmpty()) {
                payCard.setIsmaster(true);
            } else {
                payCard.setIsmaster(false);
            }
            payCardRepository.save(payCard);
            PayCard newpayCard = this.findPayCard(shopId, customerId);
            String cardNo = newpayCard.getId().toString();
            newpayCard.setCardno(cardNo);
            payCardRepository.update(newpayCard);

            return cardNo;
        }

    }

    public List<BinguoOrder> findOrderByCard(PayCard payCard){
        Condition condition = new Condition(BinguoOrder.class);
        condition.or().andEqualTo("customerid", payCard.getCustomerid())
                .andEqualTo("shopid", payCard.getShopid())
                .andEqualTo("cardid", payCard.getId())
                .andEqualTo("ordertype", OrderType.CARD.getCode().byteValue())
                .andEqualTo("paystatus", PayStatus.SUCCESS.getCode().byteValue())
                .andEqualTo("refundstatus", RefundStatus.UN_REFUND.getCode().byteValue());
        return binguoOrderRepository.findByCondition(condition);
    }




    public Optional<PayCard> findEmptyPayCardByCardNo(Integer customerId, String cardNo){
        Condition condition = new Condition(PayCard.class);
        condition.or()
                .andEqualTo("customerid", customerId)
                .andEqualTo("cardno", cardNo);
        return payCardRepository.findByCondition(condition).stream().findFirst();
    }


    public PayCard findPayCardByCardNo(Integer customerId, String cardNo){
        Condition condition = new Condition(PayCard.class);
        condition.or()
                .andEqualTo("customerid", customerId)
                .andEqualTo("cardno", cardNo)
                .andEqualTo("deleted", false);
        return payCardRepository.findByCondition(condition).stream()
                .findFirst().orElseThrow(() -> new ServiceException(WX_PAYCARD_NOT_EXIST));
    }




    public PayCard findPayCard(Integer shopId, Integer customerId){
        Condition condition = new Condition(PayCard.class);
        condition.or().andEqualTo("customerid", customerId)
                .andEqualTo("shopid", shopId)
                .andEqualTo("cardtype", CardType.BINGUO_CARD.getCode().byteValue())
                .andEqualTo("deleted", false);
        return payCardRepository.findByCondition(condition).stream()
                .findFirst().orElseThrow(() -> new ServiceException(WX_PAYCARD_NOT_EXIST));
    }





    public PayCard findById(Integer cardId, Integer customerId){
        Condition condition = new Condition(PayCard.class);
        condition.or().andEqualTo("customerid", customerId)
                .andEqualTo("id", cardId)
                .andEqualTo("deleted", false);
        return payCardRepository.findByCondition(condition).stream()
                .findFirst().orElseThrow(() -> new ServiceException(WX_PAYCARD_NOT_EXIST));
    }




    public PayCard findByCardId(Integer cardId){
        Condition condition = new Condition(PayCard.class);
        condition.or()
                .andEqualTo("id", cardId)
                .andEqualTo("deleted", false);
        return payCardRepository.findByCondition(condition).stream()
                .findFirst().orElseThrow(() -> new ServiceException(WX_PAYCARD_NOT_EXIST));
    }


    public Shop findShopById(Integer shopId){
        return shopService.findShopById(shopId);
    }


    public List<PayCard> findByCustomerId(Integer customerId){
        Condition condition = new Condition(PayCard.class);
        condition.or().andEqualTo("customerid", customerId)
                .andEqualTo("deleted", false);
        return payCardRepository.findByCondition(condition);
    }


    public List<PayCard> findBinguoCardByCustomerId(Integer customerId){
        Condition condition = new Condition(PayCard.class);
        condition.or().andEqualTo("customerid", customerId)
                .andEqualTo("cardtype", CardType.BINGUO_CARD.getCode().byteValue())
                .andEqualTo("deleted", false);
        return payCardRepository.findByCondition(condition);
    }


    public List<PayCard> findMasterCardByCustomerId(Integer customerId){
        Condition condition = new Condition(PayCard.class);
        condition.or().andEqualTo("customerid", customerId)
                .andEqualTo("cardtype", CardType.BINGUO_CARD.getCode().byteValue())
                .andEqualTo("ismaster", true)
                .andEqualTo("deleted", false);
        return payCardRepository.findByCondition(condition);
    }


    @Resource
    private CustomerExtendMapper customerExtendMapper;

    private void addCustomerExtend(Integer shopId, Integer customerId, String faceId, String faceUrl){
        Shop shop = shopService.findShopById(shopId);

        Customer customer = customerService.findByCustomerId(customerId);

        CustomerExtend condition = new CustomerExtend();
        condition.setShopId(shop.getId());
        condition.setCustomerId(customerId);

        CustomerExtend customerExtend = customerExtendMapper.selectOne(condition);

        if (customerExtend == null) {
            customerExtend = new CustomerExtend();
        }

        customerExtend.setCustomerId(customerId);

        customerExtend.setUserStatus(1);
        customerExtend.setShopId(shop.getId());

        if (shop.getAllowUserRegistry() != null && shop.getAllowUserRegistry().intValue() == 0) {
            customerExtend.setIsAudit(0);
            addDeviceMsgTemporary(customer.getName(), customerId, shopId, faceId, faceUrl, 0);
        } else {
            customerExtend.setIsAudit(1);
            addDeviceMsgTemporary(customer.getName(), customerId, shopId, faceId, faceUrl, 1);
//            deviceMsgService.addDeviceMsg(shop.getId(), customerId, customer.getName(), faceUrl, "1", faceId);
        }

        if (customerExtend.getId() == null) {
            customerExtendMapper.insertSelective(customerExtend);

        } else {
            customerExtendMapper.updateByPrimaryKeySelective(customerExtend);
        }
    }



    private void addCustomerExtendNew(Customer customer, Shop shop, Integer groupId){

        CustomerExtend condition = new CustomerExtend();
        condition.setShopId(shop.getId());
        condition.setCustomerId(customer.getId());

        CustomerExtend customerExtend = customerExtendMapper.selectOne(condition);

        if (customerExtend == null) {
            customerExtend = new CustomerExtend();
        }

        customerExtend.setCustomerId(customer.getId());

        customerExtend.setUserStatus(1);
        customerExtend.setShopId(shop.getId());
        customerExtend.setGroupId(groupId);
        

        if (shop.getAllowUserRegistry() != null && shop.getAllowUserRegistry().intValue() == 0) {
            customerExtend.setIsAudit(0);
        } else {
            customerExtend.setIsAudit(1);
        }

        if (customerExtend.getId() == null) {
            customerExtendMapper.insertSelective(customerExtend);
        } else {
            customerExtendMapper.updateByPrimaryKeySelective(customerExtend);
        }
    }

    private void addFace(Integer customerId, Integer shopId){

        Condition condition = new Condition(Face.class);
        condition.or().andEqualTo("customerId", customerId);
        List<Face> faceList = faceRepository.findByCondition(condition);

        if (faceList != null && faceList.size() > 0) {
            int i=0;
            for (Face face : faceList) {
                String faceId = null;
                try {

                    if (i==0) {
                        faceId = FaceHelperV3.createPerson(shopId.toString(), shopId + "_" + customerId, face.getFaceurl());
                    }else {
                        faceId = FaceHelperV3.addFace(shopId + "_" + customerId, face.getFaceurl());
                    }

                } catch (Exception e) {
                    LoggerUtil.console.info("e:{}", e);
                    faceId = FaceHelperV3.addFace(shopId + "_" + customerId, face.getFaceurl());
                }

                if (faceId != null) {
                    Face temp = new Face();
                    temp.setIsDeleted(0);
                    temp.setCreateTime(new Date());
                    temp.setCustomerId(customerId);
                    temp.setFaceid(faceId);
                    temp.setFaceurl(face.getFaceurl());
                    temp.setPersionid(shopId + "_" + customerId);
                    faceRepository.save(temp);
                }
            }
        }
    }



    private void addDeviceMsgTemporary(String customerName, Integer customerId, Integer shopId
            ,String faceId, String faceUrl, Integer allowStatus
    ){
        DeviceMsgTemporary deviceMsgTemporary = new DeviceMsgTemporary();
        deviceMsgTemporary.setCreateTime(new Date());
        deviceMsgTemporary.setCustomerId(customerId);
        deviceMsgTemporary.setCustomerName(customerName);
        deviceMsgTemporary.setShopId(shopId);
        deviceMsgTemporary.setMsgType(customerId);
        deviceMsgTemporary.setFaceId(faceId);
        deviceMsgTemporary.setFaceUrl(faceUrl);
        deviceMsgTemporary.setStatus(0);
        deviceMsgTemporary.setAllowStatus(allowStatus);
        deviceMsgTemporaryRepository.save(deviceMsgTemporary);
    }

}
